<template>
  <el-table
    v-bind="$attrs"
    :data="data"
    v-on="$listeners">
    <el-table-column
      label="编辑"
      align="center"
      width="70"
    >
      <template slot-scope="prop">
        <div class="action-cell" v-show="!_isEditState(prop.$index)">
          <i @click="editRow(prop.row, prop.$index)" class="icon el-icon-edit"></i>
        </div>
        <div class="action-cell" v-show="_isEditState(prop.$index)">
          <i class="icon el-icon-check" @click="commitRow(prop.row, prop.$index)"></i>
          <i class="icon el-icon-close" @click="cancelEdit(prop.$index)"></i>
        </div>
      </template>
    </el-table-column>
    <el-table-column
      v-for="( option,index ) in columnOptions"
      v-bind="option"
      :formatter="( row, column, cellValue, columnIndex ) => formatterFn( row, column, cellValue, columnIndex, option )"
    >
    </el-table-column>
  </el-table>
</template>

<script type="text/jsx">
  const _deepClone = (obj) => JSON.parse(JSON.stringify(obj))

  export default {
    created() {
      this.dataCache = _deepClone(this.data)
    },
    props: {
      data: {
        type: Array,
        default: () => []
      },
      columnOptions: {
        type: Array,
        default: () => []
      }
    },
    data() {
      return {
        // 处于编辑状态的行
        editStateRows: []
      }
    },
    methods: {
      formatterFn(row, column, cellValue, index, option) {
        // 普通模式显示在cell内的值
        let normalRender
        // 继承父元素传入的formatter jsx
        if (option.formatter) {
          normalRender = option.formatter(row, column, cellValue, index)
        } else {
          normalRender = cellValue
        }
        // 该行处于编辑状态 并且prop传入的option指定这行是可编辑
        if (row.editState && option.editable) {
          return this._editRender({row, column, cellValue, option})
        } else {
          return normalRender
        }
      },
      editRow(row, index) {
        this.$set(row, '$index', index)
        if (!this.rowCacheMap) {
          this.rowCacheMap = []
        }
        this.rowCacheMap[index] = Object.assign({}, row)
        if (row.editState) return
        if (row.editState === false) row.editState = true
        if (!row.editState) this.$set(row, 'editState', true)
      },
      commitRow(row, index) {
        this.$emit('row-commit', {row: this.data[index], index})
      },
      cancelEdit(index) {
        const dataRow = this.data[index]
        dataRow.editState = false
        const cacheRow = this.rowCacheMap[index]
        const keys = Object.keys(cacheRow)
        keys.forEach(key => {
          dataRow[key] = cacheRow[key]
        })
      },
      handleInput(val, index, field) {
        this.data[index][field] = val
      },
      addRow(row = {}) {
        this.$set(row, 'editable', true)
        this.data.unshift(row)
      },
      _isEditState(index) {
        return this.data[index].editState
      },
      _editRender({row, column, cellValue, option}) {
        const {editRender, editType, prop, options} = option
        // 用户自定义表单控件
        if (editRender) {
          return editRender(this.data[row.$index], row.$index)
        }
        // 默认提供的表单控件
        if (editType) {
          switch (editType) {
            case 'datePicker' : {
              const { customProps, customStyle, customEvent } = options
              const finalOptions = {
                props: {
                  type:"date",
                  size:"mini",
                  placeholder:"请选择日期",
                  value: row[prop],
                  format:"yyyy年MM月dd日",
                  'value-format': "yyyy-MM-dd",
                  ...customProps
                },
                style: {
                  width: '100%',
                  ...customStyle
                },
                event: {
                  input: val => row[prop] = val,
                  ...customEvent
                }
              }
              const { props, style, event } = finalOptions
              return h(
                'el-date-picker', {
                  props,
                  style,
                  on: event
                }
              )
            }
            case 'select' : {
              const { selectData,selectLabel,selectValue,renderLabel } = options
              const handleChange = (val) => {row[prop] = val}
              return (
                <el-select value={row[prop]} onChange={handleChange} style= {{width : '100%'}} filterable placeholder="请选择" size="mini">
                  {selectData.map(t => {
                    let label = t[selectLabel || 'label']
                    let value = t[selectValue || 'value'] || label
                    if ( renderLabel ) {
                      label = renderLabel(label,value)
                    }
                    return (
                      <el-option
                       label={label}
                       value={value}
                      >
                      </el-option>
                    )
                  })}
                </el-select>
              )
            }
          }
        }
        // 默认为输入框
        return (
          <el-input size="mini" onInput={val => this.handleInput(val, row.$index, prop)}
                    value={cellValue}>
          </el-input>
        )
      }
    },
    watch: {
      data: {
        handler(newVal) {
          this.editStateRows = newVal.filter(data => data.editState)
          this.$emit('edit-rows-change', this.editStateRows)
        },
        deep: true
      }
    }
  }
</script>

<style lang="stylus" rel="stylesheet/stylus" scoped>
  .action-cell
    text-align center
    white-space nowrap
    display flex
    justify-content space-around
    .icon
      font-size 17px
      cursor pointer
      transform color .5s
    .el-icon-check
      &:hover
        color #67C23A
    .el-icon-close
      &:hover
        color #F56C6C
    .el-icon-edit
      &:hover
        color #409EFF
</style>
